import {BluePrint,BluePrint2} from './BLUEPRINT'
import {DiccreepSelfAdaptation} from './SPAWN'
import {GenerateAbility,find_object_from_list, getDistance, isInArray} from '@/utils'
import { filter } from 'lodash'
import structure from '../structure'
// 用于房间的自动规划
// 房间原型拓展
export default class RoomExtension extends Room {
    /* 规划通用函数 */
    /*
    ** A型1号 注【仅用于spawn房间内】逻辑 --->
    ** 1. 以头一个spawn为起点，获取房间内的结构、建筑工地
    ** 2  按照既定结构规划 布局类型 --> 集中型
    ** 缺点：过于消耗cpu，已废弃
    */
    public plan_A1():void{
        // 每 10 tick 做一次检查
        if (Game.time % 10) return
        // 首先寻找中心虫卵，我们的一切建筑将以此为中心 一般情况下，我们将spawn1ID作为中心虫卵进行规划
        var my_spawn:StructureSpawn = Game.getObjectById(this.memory.spawn1ID)
        if (!my_spawn) return
        if (my_spawn && !this.memory.center_x && !this.memory.center_y){
            // 如果存在,考虑到有可能spawn被摧毁
            this.memory.center_x = my_spawn.pos.x
            this.memory.center_y = my_spawn.pos.y
        }
        var center_point:RoomPosition
            // 获取中心点
            center_point = new RoomPosition(this.memory.center_x,this.memory.center_y,this.name)
        // 接下来根据控制器的等级来进行相应规划
        var level:number = this.controller.level
        /* 蓝图规划部分 */
        this.writeBlueprint(level,BluePrint)
        /* 特定规划部分 */
        // sourceLink
        this.constructSourceLink()
        /* 五级后且sotrage的能量大于200K */
        this.create_rampart_construction_A1()


    }

    /*
    ** C型1号 优化A型1号逻辑，增加一些对布局选项的自由度，并通过memory降低cpu消耗
    ** 缺点：所有已经添加的结构或者道路均不能自发删除，即使删除后续也会加上，需要使用api进行解绑，api开发中...
    */
    public plan_C1(map:planData[]):void{
        // 每 25 tick 做一次检查
        if (Game.time % 25) return
        /* 中心点获取，如果本来就有就跳过 */
        if (!this.memory.controlLevel) this.memory.controlLevel = 0
        if (!this.memory.center_x)
        {
            var my_spawn:StructureSpawn = Game.getObjectById(this.memory.spawn1ID)
            if (!my_spawn) return
            this.memory.center_x = my_spawn.pos.x;this.memory.center_y = my_spawn.pos.y
        }
        const level = this.controller.level
        /* 如果升级了，启动建筑规划 */
        /* 如果memory中distribution的总数量大于实际建筑数量，启动建筑修复和扫描*/
        /* 如果distribution中的总数量小于实际建筑数量，进行distribution刷新 */
        /* 如果等于，则什么都不用干 */
        /* 如果现存结构数大于记忆中的结构树，将遍历该房间的memory，将未添加进memory的结构树添加进memory中 */
        if (level > this.memory.controlLevel)
        {
            this.writeBlueprint(level,map)
            this.memory.controlLevel = level
            console.log("建筑规划")
            /* 特定规划部分 */
            // sourceLink
            this.constructSourceLink()
        }
        // this.RampartPlan2(BluePrint2)
        // 寻找所有属于我的建筑的数量 -1是去除controller 包含所有非控制器的我方建筑、我方建筑工地、该房间内的道路，container
        let currentNum = this.find(FIND_MY_STRUCTURES).length + this.find(FIND_MY_CONSTRUCTION_SITES).length + this.find(FIND_STRUCTURES,{filter:(structure)=>{return structure.structureType == STRUCTURE_CONTAINER || structure.structureType == STRUCTURE_ROAD}}).length - 1
        if(!this.memory.structureNum) this.memory.structureNum = 0
        this.memory.structureNum = this.getDistributionNum()
        if (currentNum > this.memory.structureNum)
        {
            this.addStructureMemory()
            console.log(`房间${this.name} 更新distribution记忆!`)
        }
        else if (currentNum === this.memory.structureNum)
        {
            // console.log("无事发生")
            return
        }
        else
        {
            console.log(this.name,"检测出缺损")
            /* 运行修补函数 */
            this.repatchDistribution()
        }
    }

    /* 爬虫数量、能力自动规划通用函数 */
    /*
    ** A型1号 (已经废弃并删除) 注【仅用于spawn房间内】逻辑 | 即使有参数，但也不是控制参数，所以为 A型 ---> 
    ** 1. 从常量中获取role列表中对应的爬虫角色data，进行其数量、能力随着房价控制器等级变化的自适应操控
    */

    /*
    ** 爬虫数量自动规划2型 适应字典型的爬虫roledata | 直接从全局拉取数据，不再需要参数和传参
    */
    public Role_A2():void{
        var result = global.DicCreepFrameControl[this.name]
        if (!result) return
        var level = this.controller.level
        for (var roleKey of Object.keys(DiccreepSelfAdaptation))
        {
            if (!result[roleKey]){continue}
            var bodyArray = DiccreepSelfAdaptation[roleKey][level].bodypart
            result[roleKey].ability = GenerateAbility(bodyArray[0],bodyArray[1],bodyArray[2],bodyArray[3],bodyArray[4],bodyArray[5],bodyArray[6],bodyArray[7])
            result[roleKey].num = DiccreepSelfAdaptation[roleKey][level].num
            if (roleKey == 'repair02' && this.name == 'E49S44')
            {
                result[roleKey].ability = GenerateAbility(10,10,10)
            }
        }
        global.DicCreepFrameControl[this.name] = result
    }
    /* 由于Global缓存bug，我们还是需要参数和传参，避免未知的bug */
    public Role_A1(roleData:DicRoleData):void{
        var level = this.controller.level
        for (var roleKey of Object.keys(DiccreepSelfAdaptation))
        {
            if (!roleData[roleKey]) {continue}
            var bodyArray = DiccreepSelfAdaptation[roleKey][level].bodypart
            roleData[roleKey].ability = GenerateAbility(bodyArray[0],bodyArray[1],bodyArray[2],bodyArray[3],bodyArray[4],bodyArray[5],bodyArray[6],bodyArray[7])
            roleData[roleKey].num = DiccreepSelfAdaptation[roleKey][level].num
        }
        return
    }
    // 在较远资源点创建link
    public constructSourceLink():void
    {
        if (this.controller.level >= 5)
        {
            var source_:Source
            var source_list = this.find(FIND_SOURCES)
            if (source_list.length == 1) source_ = source_list[0]
            if (source_list.length > 1)
            {
                source_ = source_list[0]
                var con_ = this.controller
                for (var ii of source_list)
                {
                    if (getDistance(ii.pos,con_.pos) > getDistance(source_.pos,con_.pos))
                    source_ = ii
                }
            }
            if (source_)
            {
                var link_void = source_.pos.getSourceLinkVoid()
                var link_0 = source_.pos.findInRange(FIND_STRUCTURES,4,{filter:{structureType:STRUCTURE_LINK}})
                var link_c = source_.pos.findInRange(FIND_CONSTRUCTION_SITES,3)
                if (link_0.length == 0 && link_c.length == 0 && link_void.length > 0)
                    link_void[0].createConstructionSite(STRUCTURE_LINK)
            }

        }
    }
    /* 适用于plan_A1函数的rampart自动规划函数 */
    public create_rampart_construction_A1():void
    {
        var position_ = new RoomPosition(this.memory.center_x+2,this.memory.center_y,this.name)
        var storage_ = position_.getClosestStructure([STRUCTURE_STORAGE],0) as StructureStorage
        if (storage_ && storage_.store.getUsedCapacity(RESOURCE_ENERGY) >= 100000 && this.controller.level >= 5)
        {
            for (var i = position_.x - 3;i<position_.x+4;i++)
                for (var j=position_.y-2;j<position_.y+3;j++)
                {
                    let new_point = new RoomPosition(i,j,this.name)
                    new_point.createConstructionSite(STRUCTURE_RAMPART)
                }
        }
    }

    /* 遍历该房间内所有的可以建造、维修的construction site 或者 structure，将其添加进该房间的memory中 */
    public addStructureMemory():void{
        if (!this.memory.distribution) this.memory.distribution = { }
        // 获取所有的结构和工地
        var construction = []
        var all_my_structure = this.find(FIND_MY_STRUCTURES,{filter:(structure)=>{
            return structure.structureType != STRUCTURE_CONTROLLER
        }})
        var all_spawn = this.find(FIND_MY_SPAWNS)
        for (var i of all_my_structure) construction.push(i)
        for (var n of all_spawn) construction.push(n)
        var all_road = this.find(FIND_STRUCTURES,{filter:(structure)=>{
            return structure.structureType == STRUCTURE_ROAD || structure.structureType == STRUCTURE_CONTAINER
        }})
        for (var j of all_road) construction.push(j)
        var all_construct = this.find(FIND_CONSTRUCTION_SITES,{filter:(structure)=>{
            return structure.structureType != STRUCTURE_WALL
        }})
        for (var m of all_construct) construction.push(m)
        for (var index of construction)
        {
            if (!this.memory.distribution[index.structureType]) this.memory.distribution[index.structureType] = []
            if (!isInArray(this.memory.distribution[index.structureType],`${index.pos.x}/${index.pos.y}`))
            this.memory.distribution[index.structureType].push(`${index.pos.x}/${index.pos.y}`)
        }
    }

    /* 从blueprint读取数据，并根据等级进行规划 注：极耗CPU，只推荐在控制器升级时调用 */
    public writeBlueprint(level:number,map:planData[]):void
    {
        for (var index of map)
        {
            // 只有等级大于额定规划等级才会被纳入考虑
            if (level >= index.enableLevel)
            {
                let center_point:RoomPosition
                // 获取中心点
                center_point = new RoomPosition(this.memory.center_x,this.memory.center_y,this.name)
                let new_point = new RoomPosition(center_point.x + index.posX,center_point.y+index.posY,this.name)
                // 获取new_point上的建筑
                let new_point_structures = new_point.lookFor(LOOK_STRUCTURES)
                let pd:boolean = true
                if (new_point_structures.length > 0)
                    for (var j of new_point_structures)
                        {
                            if (j.structureType != STRUCTURE_RAMPART)
                            pd = false
                        }
                if (index.posType == STRUCTURE_SPAWN)
                {
                    var sl = this.getStructure(STRUCTURE_SPAWN).length
                    new_point.createConstructionSite(index.posType,`${this.name}-${sl+1}`)
                }
                else
                {
                    if (new_point && new_point.lookFor(LOOK_CONSTRUCTION_SITES).length == 0 && pd){
                        if (new_point.createConstructionSite(index.posType) != 0)
                        {
                            // console.log("创建失败:" + index.posType + '，位置为：x->'+new_point.x + ',y->'+new_point.y)
                        }
                        else
                        {
                            console.log("创建成功:" + index.posType + '，位置为：x->'+new_point.x + ',y->'+new_point.y)
                        }
                    }
                    else
                    {
                        // console.log("位置 x=",new_point.x,',y=',new_point.y,'已经有建筑或者结构了！')
                    }
                }
            }
        }
    }

    /* 获取房间memory中distribution总数量 */
    public getDistributionNum():number{
        if (!this.memory.distribution) return 0
        let result = 0
        for (var i of Object.keys(this.memory.distribution))
        {
            result += this.memory.distribution[i].length
        }
        return result
    }

    /* 修补函数，根据记忆将缺损的建筑进行自动工地规划 */
    public repatchDistribution():void{
        if (!this.memory.distribution) return
        for (var key_ of Object.keys(this.memory.distribution))
        {
            // key_ : road/spawn/storage....
            for (var po of this.memory.distribution[key_])
            {
                var thisPos = this.unzip(po)
                if (thisPos)
                {
                    if (key_ != 'spawn')
                    {
                        if (thisPos.createConstructionSite(key_ as BuildableStructureConstant) == 0 )
                        {
                            console.log(`自动修复成功，其建筑为${key_}，位置为${thisPos.x},${thisPos.y}`)
                        }
                    }
                    else
                    {
                        thisPos.createConstructionSite(STRUCTURE_SPAWN)
                    }
                }
            }
        }
        
    }

    /* 解绑函数，删除memory中指定的数据 */
    public unbindMemory(mold:BuildableStructureConstant,x:number,y:number):void{
        var thisPosition:RoomPosition = new RoomPosition(x,y,this.name)
        if (thisPosition.lookFor(LOOK_STRUCTURES).length ==0 && thisPosition.lookFor(LOOK_CONSTRUCTION_SITES).length == 0)
        {
            console.log(`房间${this.name}的位置x:${thisPosition.x},y:${thisPosition.y}无任何建筑或工地！`)
            return
        }
        var result = []
        for (var i of thisPosition.lookFor(LOOK_STRUCTURES)) result.push(i)
        for (var j of thisPosition.lookFor(LOOK_CONSTRUCTION_SITES)) result.push(j)
        for (var sample of result)
        {
            if (sample.structureType === mold)
            {
                // 在记忆列表中删除指定的数据，并删除该位置的建筑或工地
                if (!this.memory.distribution[mold]) return
                if (this.memory.distribution[mold].length <= 0) return
                for (var poStr of this.memory.distribution[mold])
                {
                    if (poStr == `${x}/${y}`)
                    {
                        var index = this.memory.distribution[mold].indexOf(poStr)
                        if(index > -1) {
                            this.memory.distribution[mold].splice(index,1);
                        }
                    }
                }
                if(sample.destroy) sample.destroy()
                else if (sample.remove) sample.remove()
                return
                
            }
        }
        console.log(`房间${this.name}的位置x:${thisPosition.x},y:${thisPosition.y}不存在${mold}类型建筑或结构！`)
    }

    /* BluePrint2 对应的rampart规划 手动控制 */
    public RampartPlan2(name:string):void{
        if (!this.memory.center_x) return
        /* rampart规划部分 */
        var storage_ = this.getStructure(STRUCTURE_STORAGE) as StructureStorage[]
        if (storage_.length > 0 && this.name == name)
        {
            if (storage_[0].store.getUsedCapacity(RESOURCE_ENERGY) > 0)
            {
                var circle_x = this.memory.center_x
                var circle_y = this.memory.center_y - 2
                for (var i=circle_x-9;i<circle_x+10;i++)
                    for (var j=circle_y-9;j<circle_y+10;j++)
                    {
                        // 去除无关的位置
                        if (Math.abs(j-circle_y)== 9 ||  Math.abs(i-circle_x) == 9)
                        {
                            var new_place = new RoomPosition(i,j,this.name)
                            if ((Math.abs(j-circle_y) + Math.abs(i-circle_x)) % 2)
                            {
                                new_place.createConstructionSite(STRUCTURE_RAMPART)
                            }
                            else
                            {
                                var look_str = new_place.lookFor(LOOK_STRUCTURES)
                                if (look_str.length > 0)
                                {
                                    for (var s of look_str)
                                        if (s.structureType == STRUCTURE_ROAD || s.structureType == STRUCTURE_CONTAINER || s.structureType == STRUCTURE_LINK)
                                        new_place.createConstructionSite(STRUCTURE_RAMPART)
                                }
                                else
                                    new_place.createConstructionSite(STRUCTURE_WALL)
                                if (new_place.findInRange(FIND_SOURCES,1).length > 0)
                                {
                                    new_place.createConstructionSite(STRUCTURE_RAMPART)
                                }
                            }
                        }
                        
                    }
            }
        }
    }

    
}